///PHILOTES Source Code.  (C)2012 PhiloLabs
#pragma once

#ifndef __SceneManager_H__
#define __SceneManager_H__

// Precompiler options
#include "OgrePrerequisites.h"

#include "OgreString.h"
#include "OgreSceneNode.h"
#include "math/plane.h"
#include "math/quaternion.h"
#include "util/colourValue.h"
#include "OgreCommon.h"
#include "OgreSceneQuery.h"
#include "OgreAutoParamDataSource.h"
#include "OgreAnimationState.h"
#include "OgreRenderQueue.h"
#include "OgreRenderQueueSortingGrouping.h"
#include "OgreRectangle2D.h"
#include "OgrePixelFormat.h"
#include "OgreResourceGroupManager.h"
#include "OgreTexture.h"
#include "OgreShadowCameraSetup.h"
#include "OgreShadowTextureManager.h"
#include "OgreCamera.h"
#include "OgreInstancedGeometry.h"
#include "OgreLodListener.h"
#include "OgreInstanceManager.h"
#include "OgreRenderSystem.h"
namespace Ogre {
	
	

    
    struct ViewPoint
    {
        Vector3 position;
        Quaternion orientation;
    };

	// Forward declarations
	class DefaultIntersectionSceneQuery;
	class DefaultRaySceneQuery;
	class DefaultSphereSceneQuery;
	class DefaultAxisAlignedBoxSceneQuery;
	class CompositorChain;

	
	struct _OgreExport VisibleObjectsBoundsInfo
	{
		/// The axis-aligned bounds of the visible objects
		AxisAlignedBox aabb;
		/// The axis-aligned bounds of the visible shadow receiver objects
		AxisAlignedBox receiverAabb;
		/// The closest a visible object is to the camera
		Real minDistance;
		/// The farthest a visible objects is from the camera
		Real maxDistance;
		/// The closest a object in the frustum regardless of visibility / shadow caster flags
		Real minDistanceInFrustum;
		/// The farthest object in the frustum regardless of visibility / shadow caster flags
		Real maxDistanceInFrustum;

		VisibleObjectsBoundsInfo();
		void reset();
		void merge(const AxisAlignedBox& boxBounds, const Sphere& sphereBounds, 
			const Camera* cam, bool receiver=true);
		
		void mergeNonRenderedButInFrustum(const AxisAlignedBox& boxBounds, 
			const Sphere& sphereBounds, const Camera* cam);


	};

    
	class _OgreExport SceneManager : public MemAlloc_SceneCtrl
    {
    public:
        /// Query type mask which will be used for world geometry @see SceneQuery
        static uint32 WORLD_GEOMETRY_TYPE_MASK;
		/// Query type mask which will be used for entities @see SceneQuery
		static uint32 ENTITY_TYPE_MASK;
		/// Query type mask which will be used for effects like billboardsets / particle systems @see SceneQuery
		static uint32 FX_TYPE_MASK;
		/// Query type mask which will be used for StaticGeometry  @see SceneQuery
		static uint32 STATICGEOMETRY_TYPE_MASK;
		/// Query type mask which will be used for lights  @see SceneQuery
		static uint32 LIGHT_TYPE_MASK;
		/// Query type mask which will be used for frusta and cameras @see SceneQuery
		static uint32 FRUSTUM_TYPE_MASK;
		/// User type mask limit
		static uint32 USER_TYPE_MASK_LIMIT;
        
        struct materialLess
        {
            _OgreExport bool operator()(const Material* x, const Material* y) const;
        };
        /// Comparator for sorting lights relative to a point
        struct lightLess
        {
            _OgreExport bool operator()(const Light* a, const Light* b) const;
        };

        /// Describes the stage of rendering when performing complex illumination
        enum IlluminationRenderStage
        {
            /// No special illumination stage
            IRS_NONE,
            /// Render to texture stage, used for texture based shadows
            IRS_RENDER_TO_TEXTURE,
            /// Render from shadow texture to receivers stage
            IRS_RENDER_RECEIVER_PASS
        };

		
		enum SpecialCaseRenderQueueMode
		{
			/// Render only the queues in the special case list
			SCRQM_INCLUDE,
			/// Render all except the queues in the special case list
			SCRQM_EXCLUDE
		};

		struct SkyDomeGenParameters
		{
			Real skyDomeCurvature;
			Real skyDomeTiling;
			Real skyDomeDistance;
			int skyDomeXSegments; 
			int skyDomeYSegments;
			int skyDomeYSegments_keep;
		};

		struct SkyPlaneGenParameters
		{
			Real skyPlaneScale;
			Real skyPlaneTiling; 
			Real skyPlaneBow; 
			int skyPlaneXSegments; 
			int skyPlaneYSegments; 
		};

// 		struct SkyBoxGenParameters
// 		{
// 			Real skyBoxDistance;
// 		};

		
		class Listener
		{
		public:
			Listener() {}
			virtual ~Listener() {}

			
			virtual void preUpdateSceneGraph(SceneManager* source, Camera* camera)
                        { (void)source; (void)camera; }

			
			virtual void postUpdateSceneGraph(SceneManager* source, Camera* camera)
                        { (void)source; (void)camera; }

			
			virtual void preFindVisibleObjects(SceneManager* source, 
				IlluminationRenderStage irs, Viewport* v)
                        { (void)source; (void)irs; (void)v; }

			
			virtual void postFindVisibleObjects(SceneManager* source, 
				IlluminationRenderStage irs, Viewport* v)
                        { (void)source; (void)irs; (void)v; }

			
			virtual void shadowTexturesUpdated(size_t numberOfShadowTextures)
                        { (void)numberOfShadowTextures; }

			
			virtual void shadowTextureCasterPreViewProj(Light* light, 
				Camera* camera, size_t iteration)
                        { (void)light; (void)camera; (void)iteration; }

			
			virtual void shadowTextureReceiverPreViewProj(Light* light, 
				Frustum* frustum)
                        { (void)light; (void)frustum; }

			
			virtual bool sortLightsAffectingFrustum(LightList& lightList)
                        { (void)lightList; return false; }

			
			virtual void sceneManagerDestroyed(SceneManager* source)
                        { (void)source; }
		};

		
		class _OgreExport SceneMgrQueuedRenderableVisitor : public QueuedRenderableVisitor
		{
		protected:
			/// Pass that was actually used at the grouping level
			const Pass* mUsedPass;
		public:
			SceneMgrQueuedRenderableVisitor() 
				:transparentShadowCastersMode(false) {}
			~SceneMgrQueuedRenderableVisitor() {}
			void visit(Renderable* r);
			bool visit(const Pass* p);
			void visit(RenderablePass* rp);

			/// Target SM to send renderables to
			SceneManager* targetSceneMgr;
			/// Are we in transparent shadow caster mode?
			bool transparentShadowCastersMode;
			/// Automatic light handling?
			bool autoLights;
			/// Manual light list
			const LightList* manualLightList;
			/// Scissoring if requested?
			bool scissoring;

		};
		/// Allow visitor helper to access protected methods
		friend class SceneMgrQueuedRenderableVisitor;

    protected:

        /// Subclasses can override this to ensure their specialised SceneNode is used.
        virtual SceneNode* createSceneNodeImpl(void);
        /// Subclasses can override this to ensure their specialised SceneNode is used.
        virtual SceneNode* createSceneNodeImpl(const String& name);

		/// Instance name
		String mName;

        /// Queue of objects for rendering
        RenderQueue* mRenderQueue;
		bool mLastRenderQueueInvocationCustom;

        /// Current ambient light, cached for RenderSystem
        ColourValue mAmbientLight;

        /// The rendering system to send the scene to
        RenderSystem *mDestRenderSystem;

        typedef map<String, Camera* >::type CameraList;

        
        CameraList mCameras;

		typedef map<String, StaticGeometry* >::type StaticGeometryList;
		StaticGeometryList mStaticGeometryList;
		typedef map<String, InstancedGeometry* >::type InstancedGeometryList;
		InstancedGeometryList mInstancedGeometryList;

		typedef map<String, InstanceManager*>::type InstanceManagerMap;
		InstanceManagerMap	mInstanceManagerMap;

        typedef map<String, SceneNode*>::type SceneNodeList;

        
        SceneNodeList mSceneNodes;

        /// Camera in progress
        Camera* mCameraInProgress;
        /// Current Viewport
        Viewport* mCurrentViewport;

        /// Root scene node
        SceneNode* mSceneRoot;

        /// Autotracking scene nodes
        typedef set<SceneNode*>::type AutoTrackingSceneNodes;
        AutoTrackingSceneNodes mAutoTrackingSceneNodes;

        // Sky params
        // Sky plane
        Entity* mSkyPlaneEntity;
        Entity* mSkyDomeEntity[5];
//        ManualObject* mSkyBoxObj;

        SceneNode* mSkyPlaneNode;
        SceneNode* mSkyDomeNode;
//        SceneNode* mSkyBoxNode;

        // Sky plane
        bool mSkyPlaneEnabled;
        uint8 mSkyPlaneRenderQueue;
        Plane mSkyPlane;
        SkyPlaneGenParameters mSkyPlaneGenParameters;

        // Sky box
//         bool mSkyBoxEnabled;
//         uint8 mSkyBoxRenderQueue;
//         Quaternion mSkyBoxOrientation;
//         SkyBoxGenParameters mSkyBoxGenParameters;

        // Sky dome
        bool mSkyDomeEnabled;
        uint8 mSkyDomeRenderQueue;
        Quaternion mSkyDomeOrientation;
        SkyDomeGenParameters mSkyDomeGenParameters;

        // Fog
        FogMode mFogMode;
        ColourValue mFogColour;
        Real mFogStart;
        Real mFogEnd;
        Real mFogDensity;

		typedef set<uint8>::type SpecialCaseRenderQueueList;
		SpecialCaseRenderQueueList mSpecialCaseQueueList;
		SpecialCaseRenderQueueMode mSpecialCaseQueueMode;
		uint8 mWorldGeometryRenderQueue;
		
		unsigned long mLastFrameNumber;
		Matrix4 mTempXform[256];
		bool mResetIdentityView;
		bool mResetIdentityProj;

		bool mNormaliseNormalsOnScale;
		bool mFlipCullingOnNegativeScale;
		CullingMode mPassCullingMode;

	protected:

		
		typedef map< const Camera*, VisibleObjectsBoundsInfo>::type CamVisibleObjectsMap;
		CamVisibleObjectsMap mCamVisibleObjectsMap; 

		
		typedef map< const Camera*, const Light* >::type ShadowCamLightMapping;
		ShadowCamLightMapping mShadowCamLightMapping;

		/// Array defining shadow count per light type.
		size_t mShadowTextureCountPerType[3];

		/// Array defining shadow texture index in light list.
		vector<size_t>::type mShadowTextureIndexLightList;

        /// Cached light information, used to tracking light's changes
        struct _OgreExport LightInfo
        {
            Light* light;       // Just a pointer for comparison, the light might destroyed for some reason
            int type;           // Use int instead of Light::LightTypes to avoid header file dependence
            Real range;         // Sets to zero if directional light
            Vector3 position;   // Sets to zero if directional light
			uint32 lightMask;   // Light mask

            bool operator== (const LightInfo& rhs) const
            {
                return light == rhs.light && type == rhs.type &&
                    range == rhs.range && position == rhs.position && lightMask == rhs.lightMask;
            }

            bool operator!= (const LightInfo& rhs) const
            {
                return !(*this == rhs);
            }
        };

        typedef vector<LightInfo>::type LightInfoList;

        LightList mLightsAffectingFrustum;
        LightInfoList mCachedLightInfos;
		LightInfoList mTestLightInfos; // potentially new list
        ulong mLightsDirtyCounter;
		LightList mShadowTextureCurrentCasterLightList;

		typedef map<String, MovableObject*>::type MovableObjectMap;
		/// Simple structure to hold MovableObject map and a mutex to go with it.
		struct MovableObjectCollection
		{
			MovableObjectMap map;
			OGRE_MUTEX(mutex)
		};
		typedef map<String, MovableObjectCollection*>::type MovableObjectCollectionMap;
		MovableObjectCollectionMap mMovableObjectCollectionMap;
		NameGenerator mMovableNameGenerator;
		
		MovableObjectCollection* getMovableObjectCollection(const String& typeName);
		
		const MovableObjectCollection* getMovableObjectCollection(const String& typeName) const;
		/// Mutex over the collection of MovableObject types
		OGRE_MUTEX(mMovableObjectCollectionMapMutex)

        
        virtual void initRenderQueue(void);
        /// A pass designed to let us render shadow colour on white for texture shadows
        Pass* mShadowCasterPlainBlackPass;
        /// A pass designed to let us render shadow receivers for texture shadows
        Pass* mShadowReceiverPass;
        
        virtual const Pass* deriveShadowCasterPass(const Pass* pass);
        
        virtual const Pass* deriveShadowReceiverPass(const Pass* pass);
    
        
        virtual bool validatePassForRendering(const Pass* pass);

        
        virtual bool validateRenderableForRendering(const Pass* pass, const Renderable* rend);

        enum BoxPlane
        {
            BP_FRONT = 0,
            BP_BACK = 1,
            BP_LEFT = 2,
            BP_RIGHT = 3,
            BP_UP = 4,
            BP_DOWN = 5
        };

        /* Internal utility method for creating the planes of a skybox.
        */
        virtual MeshPtr createSkyboxPlane(
            BoxPlane bp,
            Real distance,
            const Quaternion& orientation,
            const String& groupName);

        /* Internal utility method for creating the planes of a skydome.
        */
        virtual MeshPtr createSkydomePlane(
            BoxPlane bp,
            Real curvature, Real tiling, Real distance,
            const Quaternion& orientation,
            int xsegments, int ysegments, int ySegmentsToKeep, 
            const String& groupName);

        // Flag indicating whether SceneNodes will be rendered as a set of 3 axes
        bool mDisplayNodes;

        /// Storage of animations, lookup by name
        typedef map<String, Animation*>::type AnimationList;
        AnimationList mAnimationsList;
		OGRE_MUTEX(mAnimationsListMutex)
        AnimationStateSet mAnimationStates;


        
        virtual void useRenderableViewProjMode(const Renderable* pRend, bool fixedFunction);
        
        
        virtual void resetViewProjMode(bool fixedFunction);

        typedef vector<RenderQueueListener*>::type RenderQueueListenerList;
        RenderQueueListenerList mRenderQueueListeners;

		typedef vector<RenderObjectListener*>::type RenderObjectListenerList;
		RenderObjectListenerList mRenderObjectListeners;
        typedef vector<Listener*>::type ListenerList;
        ListenerList mListeners;
		/// Internal method for firing the queue start event
		virtual void firePreRenderQueues();
		/// Internal method for firing the queue end event
		virtual void firePostRenderQueues();
        /// Internal method for firing the queue start event, returns true if queue is to be skipped
        virtual bool fireRenderQueueStarted(uint8 id, const String& invocation);
        /// Internal method for firing the queue end event, returns true if queue is to be repeated
        virtual bool fireRenderQueueEnded(uint8 id, const String& invocation);
		/// Internal method for firing when rendering a single object.
		virtual void fireRenderSingleObject(Renderable* rend, const Pass* pass, const AutoParamDataSource* source, 
			const LightList* pLightList, bool suppressRenderStateChanges);

		/// Internal method for firing the texture shadows updated event
        virtual void fireShadowTexturesUpdated(size_t numberOfShadowTextures);
		/// Internal method for firing the pre caster texture shadows event
        virtual void fireShadowTexturesPreCaster(Light* light, Camera* camera, size_t iteration);
		/// Internal method for firing the pre receiver texture shadows event
        virtual void fireShadowTexturesPreReceiver(Light* light, Frustum* f);
		/// Internal method for firing pre update scene graph event
		virtual void firePreUpdateSceneGraph(Camera* camera);
		/// Internal method for firing post update scene graph event
		virtual void firePostUpdateSceneGraph(Camera* camera);
		/// Internal method for firing find visible objects event
		virtual void firePreFindVisibleObjects(Viewport* v);
		/// Internal method for firing find visible objects event
		virtual void firePostFindVisibleObjects(Viewport* v);
		/// Internal method for firing destruction event
		virtual void fireSceneManagerDestroyed();
        
        virtual void setViewport(Viewport *vp);

		
		bool mShowBoundingBoxes;      

		
		virtual void renderVisibleObjectsDefaultSequence(void);
		
		virtual void renderVisibleObjectsCustomSequence(RenderQueueInvocationSequence* s);
		
		virtual void prepareRenderQueue(void);


        
        virtual void renderSingleObject(Renderable* rend, const Pass* pass, 
			bool lightScissoringClipping, bool doLightIteration, const LightList* manualLightList = 0);

		
		virtual AutoParamDataSource* createAutoParamDataSource(void) const
		{
			return PHILO_NEW AutoParamDataSource();
		}

        /// Utility class for calculating automatic parameters for gpu programs
        AutoParamDataSource* mAutoParamDataSource;

		CompositorChain* mActiveCompositorChain;
		bool mLateMaterialResolving;

        ShadowTechnique mShadowTechnique;
        bool mDebugShadows;
        ColourValue mShadowColour;
        Pass* mShadowDebugPass;
        Pass* mShadowStencilPass;
        Pass* mShadowModulativePass;
		bool mShadowMaterialInitDone;
        HardwareIndexBufferSharedPtr mShadowIndexBuffer;
		size_t mShadowIndexBufferSize;
        Rectangle2D* mFullScreenQuad;
        Real mShadowDirLightExtrudeDist;
        IlluminationRenderStage mIlluminationStage;
		ShadowTextureConfigList mShadowTextureConfigList;
		bool mShadowTextureConfigDirty;
        ShadowTextureList mShadowTextures;
		TexturePtr mNullShadowTexture;
		typedef vector<Camera*>::type ShadowTextureCameraList;
		ShadowTextureCameraList mShadowTextureCameras;
        Texture* mCurrentShadowTexture;
		bool mShadowUseInfiniteFarPlane;
		bool mShadowCasterRenderBackFaces;
		bool mShadowAdditiveLightClip;
		/// Struct for cacheing light clipping information for re-use in a frame
		struct LightClippingInfo
		{
			RealRect scissorRect;
			PlaneList clipPlanes;
			bool scissorValid;
			unsigned long clipPlanesValid;
			LightClippingInfo() : scissorValid(false), clipPlanesValid(false) {}

		};
		typedef map<Light*, LightClippingInfo>::type LightClippingInfoMap;
		LightClippingInfoMap mLightClippingInfoMap;
		unsigned long mLightClippingInfoMapFrameNumber;

		/// default shadow camera setup
		ShadowCameraSetupPtr mDefaultShadowCameraSetup;

		
		struct lightsForShadowTextureLess
		{
			_OgreExport bool operator()(const Light* l1, const Light* l2) const;
		};


        
        virtual void findLightsAffectingFrustum(const Camera* camera);
        /// Internal method for setting up materials for shadows
        virtual void initShadowVolumeMaterials(void);
        /// Internal method for creating shadow textures (texture-based shadows)
        virtual void ensureShadowTexturesCreated();
        /// Internal method for destroying shadow textures (texture-based shadows)
        virtual void destroyShadowTextures(void);

		typedef vector<InstanceManager*>::type		InstanceManagerVec;
		InstanceManagerVec mDirtyInstanceManagers;
		InstanceManagerVec mDirtyInstanceMgrsTmp;

		
		void updateDirtyInstanceManagers(void);
        
	public:
		/// Method for preparing shadow textures ready for use in a regular render
		/// Do not call manually unless before frame start or rendering is paused
		/// If lightList is not supplied, will render all lights in frustum
        virtual void prepareShadowTextures(Camera* cam, Viewport* vp, const LightList* lightList = 0);

		//A render context, used to store internal data for pausing/resuming rendering
		struct RenderContext
		{
			RenderQueue* renderQueue;	
			Viewport* viewport;
			Camera* camera;
			CompositorChain* activeChain;
			RenderSystem::RenderSystemContext* rsContext;
		};

		
		virtual RenderContext* _pauseRendering();
		
		virtual void _resumeRendering(RenderContext* context);

	protected:
        
        virtual void renderShadowVolumesToStencil(const Light* light, const Camera* cam, 
			bool calcScissor);
        
        virtual void setShadowVolumeStencilState(bool secondpass, bool zfail, bool twosided);
        
        void renderShadowVolumeObjects(ShadowCaster::ShadowRenderableListIterator iShadowRenderables,
            Pass* pass, const LightList *manualLightList, unsigned long flags,
            bool secondpass, bool zfail, bool twosided);
        typedef vector<ShadowCaster*>::type ShadowCasterList;
        ShadowCasterList mShadowCasterList;
        SphereSceneQuery* mShadowCasterSphereQuery;
        AxisAlignedBoxSceneQuery* mShadowCasterAABBQuery;
        Real mDefaultShadowFarDist;
        Real mDefaultShadowFarDistSquared;
        Real mShadowTextureOffset; // proportion of texture offset in view direction e.g. 0.4
        Real mShadowTextureFadeStart; // as a proportion e.g. 0.6
        Real mShadowTextureFadeEnd; // as a proportion e.g. 0.9
		bool mShadowTextureSelfShadow;
		Pass* mShadowTextureCustomCasterPass;
		Pass* mShadowTextureCustomReceiverPass;
		String mShadowTextureCustomCasterVertexProgram;
		String mShadowTextureCustomCasterFragmentProgram;
		String mShadowTextureCustomReceiverVertexProgram;
		String mShadowTextureCustomReceiverFragmentProgram;
		GpuProgramParametersSharedPtr mShadowTextureCustomCasterVPParams;
		GpuProgramParametersSharedPtr mShadowTextureCustomCasterFPParams;
		GpuProgramParametersSharedPtr mShadowTextureCustomReceiverVPParams;
		GpuProgramParametersSharedPtr mShadowTextureCustomReceiverFPParams;

		/// Visibility mask used to show / hide objects
		uint32 mVisibilityMask;
		bool mFindVisibleObjects;

		/// Suppress render state changes?
		bool mSuppressRenderStateChanges;
		/// Suppress shadows?
		bool mSuppressShadows;


        GpuProgramParametersSharedPtr mInfiniteExtrusionParams;
        GpuProgramParametersSharedPtr mFiniteExtrusionParams;

        /// Inner class to use as callback for shadow caster scene query
        class _OgreExport ShadowCasterSceneQueryListener : public SceneQueryListener, public MemAlloc_SceneCtrl
        {
        protected:
			SceneManager* mSceneMgr;
            ShadowCasterList* mCasterList;
            bool mIsLightInFrustum;
            const PlaneBoundedVolumeList* mLightClipVolumeList;
            const Camera* mCamera;
            const Light* mLight;
            Real mFarDistSquared;
        public:
            ShadowCasterSceneQueryListener(SceneManager* sm) : mSceneMgr(sm),
				mCasterList(0), mIsLightInFrustum(false), mLightClipVolumeList(0), 
                mCamera(0) {}
            // Prepare the listener for use with a set of parameters  
            void prepare(bool lightInFrustum, 
                const PlaneBoundedVolumeList* lightClipVolumes, 
                const Light* light, const Camera* cam, ShadowCasterList* casterList, 
                Real farDistSquared) 
            {
                mCasterList = casterList;
                mIsLightInFrustum = lightInFrustum;
                mLightClipVolumeList = lightClipVolumes;
                mCamera = cam;
                mLight = light;
                mFarDistSquared = farDistSquared;
            }
            bool queryResult(MovableObject* object);
            bool queryResult(SceneQuery::WorldFragment* fragment);
        };

        ShadowCasterSceneQueryListener* mShadowCasterQueryListener;

        
        virtual const ShadowCasterList& findShadowCastersForLight(const Light* light, 
            const Camera* camera);
        
		virtual void renderBasicQueueGroupObjects(RenderQueueGroup* pGroup, 
			QueuedRenderableCollection::OrganisationMode om);
		
		virtual void renderAdditiveStencilShadowedQueueGroupObjects(RenderQueueGroup* group, 
			QueuedRenderableCollection::OrganisationMode om);
		
		virtual void renderModulativeStencilShadowedQueueGroupObjects(RenderQueueGroup* group, 
			QueuedRenderableCollection::OrganisationMode om);
        
		virtual void renderTextureShadowCasterQueueGroupObjects(RenderQueueGroup* group, 
			QueuedRenderableCollection::OrganisationMode om);
        
		virtual void renderTextureShadowReceiverQueueGroupObjects(RenderQueueGroup* group, 
			QueuedRenderableCollection::OrganisationMode om);
        
		virtual void renderModulativeTextureShadowedQueueGroupObjects(RenderQueueGroup* group, 
			QueuedRenderableCollection::OrganisationMode om);

		
		virtual void renderAdditiveTextureShadowedQueueGroupObjects(RenderQueueGroup* group, 
			QueuedRenderableCollection::OrganisationMode om);
		
		virtual void renderObjects(const QueuedRenderableCollection& objs, 
			QueuedRenderableCollection::OrganisationMode om, bool lightScissoringClipping,
            bool doLightIteration, const LightList* manualLightList = 0);
		
		virtual void renderTransparentShadowCasterObjects(const QueuedRenderableCollection& objs, 
			QueuedRenderableCollection::OrganisationMode om, bool lightScissoringClipping,
			bool doLightIteration, const LightList* manualLightList = 0);

		
		virtual void updateRenderQueueSplitOptions(void);
		
		virtual void updateRenderQueueGroupSplitOptions(RenderQueueGroup* group, 
			bool suppressShadows, bool suppressRenderState);

		/// Set up a scissor rectangle from a group of lights
		virtual ClipResult buildAndSetScissor(const LightList& ll, const Camera* cam);
		/// Update a scissor rectangle from a single light
		virtual void buildScissor(const Light* l, const Camera* cam, RealRect& rect);
		virtual void resetScissor();
		/// Build a set of user clip planes from a single non-directional light
		virtual ClipResult buildAndSetLightClip(const LightList& ll);
		virtual void buildLightClip(const Light* l, PlaneList& planes);
		virtual void resetLightClip();
		virtual void checkCachedLightClippingInfo();

		/// The active renderable visitor class - subclasses could override this
		SceneMgrQueuedRenderableVisitor* mActiveQueuedRenderableVisitor;
		/// Storage for default renderable visitor
		SceneMgrQueuedRenderableVisitor mDefaultQueuedRenderableVisitor;

		/// Whether to use camera-relative rendering
		bool mCameraRelativeRendering;
		Matrix4 mCachedViewMatrix;
		Vector3 mCameraRelativePosition;

		/// Last light sets
		uint32 mLastLightHash;
		unsigned short mLastLightLimit;
		uint32 mLastLightHashGpuProgram;
		/// Gpu params that need rebinding (mask of GpuParamVariability)
		uint16 mGpuParamsDirty;

		virtual void useLights(const LightList& lights, unsigned short limit);
		virtual void setViewMatrix(const Matrix4& m);
		virtual void useLightsGpuProgram(const Pass* pass, const LightList* lights);
		virtual void bindGpuProgram(GpuProgram* prog);
		virtual void updateGpuProgramParameters(const Pass* p);








        /// Set of registered lod listeners
        typedef set<LodListener*>::type LodListenerSet;
        LodListenerSet mLodListeners;

        /// List of movable object lod changed events
		typedef vector<MovableObjectLodChangedEvent>::type MovableObjectLodChangedEventList;
        MovableObjectLodChangedEventList mMovableObjectLodChangedEvents;

        /// List of entity mesh lod changed events
        typedef vector<EntityMeshLodChangedEvent>::type EntityMeshLodChangedEventList;
        EntityMeshLodChangedEventList mEntityMeshLodChangedEvents;

        /// List of entity material lod changed events
        typedef vector<EntityMaterialLodChangedEvent>::type EntityMaterialLodChangedEventList;
        EntityMaterialLodChangedEventList mEntityMaterialLodChangedEvents;

    public:
        
        SceneManager(const String& instanceName);

        
        virtual ~SceneManager();


		
		OGRE_MUTEX(sceneGraphMutex)

		
		const String& getName(void) const { return mName; }

		
		virtual const String& getTypeName(void) const = 0;

        
        virtual Camera* createCamera(const String& name);

        
        virtual Camera* getCamera(const String& name) const;

		
		virtual bool hasCamera(const String& name) const;

        
        virtual void destroyCamera(Camera *cam);

        
        virtual void destroyCamera(const String& name);

        
        virtual void destroyAllCameras(void);

        
        virtual Light* createLight(const String& name);

		
		virtual Light* createLight();

        
        virtual Light* getLight(const String& name) const;

		
		virtual bool hasLight(const String& name) const;

		
		virtual const PlaneList& getLightClippingPlanes(Light* l);

		
		virtual const RealRect& getLightScissorRect(Light* l, const Camera* cam);

		
        virtual void destroyLight(const String& name);

        
        virtual void destroyLight(Light* light);
        
        virtual void destroyAllLights(void);

        
        virtual void _notifyLightsDirty(void);

        
        ulong _getLightsDirtyCounter(void) const { return mLightsDirtyCounter; }

        
        virtual const LightList& _getLightsAffectingFrustum(void) const;

        
        virtual void _populateLightList(const Vector3& position, Real radius, LightList& destList, uint32 lightMask = 0xFFFFFFFF);

		
        virtual void _populateLightList(const SceneNode* sn, Real radius, LightList& destList, uint32 lightMask = 0xFFFFFFFF);

        
        virtual SceneNode* createSceneNode(void);

        
        virtual SceneNode* createSceneNode(const String& name);

        
        virtual void destroySceneNode(const String& name);

        
        virtual void destroySceneNode(SceneNode* sn);
        
        virtual SceneNode* getRootSceneNode(void);

        
        virtual SceneNode* getSceneNode(const String& name) const;

		
		virtual bool hasSceneNode(const String& name) const;


        
        virtual Entity* createEntity(const String& entityName, const String& meshName, const String& groupName = ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME );

        
        virtual Entity* createEntity(const String& entityName, const MeshPtr& pMesh );

        
        virtual Entity* createEntity(const String& meshName);

        
        virtual Entity* createEntity(const MeshPtr& pMesh);

        
        enum PrefabType {
            PT_PLANE,
			PT_CUBE,
			PT_SPHERE
        };

        
        virtual Entity* createEntity(const String& entityName, PrefabType ptype);

        virtual Entity* createEntity(PrefabType ptype);
        
        virtual Entity* getEntity(const String& name) const;
		
		virtual bool hasEntity(const String& name) const;

        virtual void destroyEntity(Entity* ent);

        virtual void destroyEntity(const String& name);

        virtual void destroyAllEntities(void);

        
//         virtual ManualObject* createManualObject(const String& name);
// 		
// 		virtual ManualObject* createManualObject();
//         
//         virtual ManualObject* getManualObject(const String& name) const;
// 		
// 		virtual bool hasManualObject(const String& name) const;
// 
//         
//         virtual void destroyManualObject(ManualObject* obj);
// 		
// 		virtual void destroyManualObject(const String& name);
// 		
// 		virtual void destroyAllManualObjects(void);
		
        virtual void clearScene(void);

        void setAmbientLight(const ColourValue& colour);

        const ColourValue& getAmbientLight(void) const;

        virtual void prepareWorldGeometry(const String& filename);

		virtual void prepareWorldGeometry(DataStreamPtr& stream, 
			const String& typeName = StringUtil::BLANK);

        virtual void setWorldGeometry(const String& filename);

		virtual void setWorldGeometry(DataStreamPtr& stream, 
			const String& typeName = StringUtil::BLANK);

        virtual size_t estimateWorldGeometry(const String& filename)
        { (void)filename; return 0; }
	
        virtual size_t estimateWorldGeometry(DataStreamPtr& stream, 
			const String& typeName = StringUtil::BLANK)
        { (void)stream; (void)typeName; return 0; }

        virtual ViewPoint getSuggestedViewpoint(bool random = false);

        virtual bool setOption( const String& strKey, const void* pValue )
        { (void)strKey; (void)pValue; return false; }

        virtual bool getOption( const String& strKey, void* pDestValue )
        { (void)strKey; (void)pDestValue; return false; }

        virtual bool hasOption( const String& strKey ) const
        { (void)strKey; return false; }

        virtual bool getOptionValues( const String& strKey, StringVector& refValueList )
        { (void)strKey; (void)refValueList; return false; }

        virtual bool getOptionKeys( StringVector& refKeys )
        { (void)refKeys; return false; }

        virtual void _updateSceneGraph(Camera* cam);

        virtual void _findVisibleObjects(Camera* cam, VisibleObjectsBoundsInfo* visibleBounds, bool onlyShadowCasters);

        virtual void _applySceneAnimations(void);

        virtual void _renderVisibleObjects(void);

        virtual void _renderScene(Camera* camera, Viewport* vp, bool includeOverlays);

        virtual void _queueSkiesForRendering(Camera* cam);

        virtual void _setDestinationRenderSystem(RenderSystem* sys);

        virtual void setSkyPlane(
            bool enable,
            const Plane& plane, const String& materialName, Real scale = 1000,
            Real tiling = 10, bool drawFirst = true, Real bow = 0, 
            int xsegments = 1, int ysegments = 1, 
            const String& groupName = ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
                
        virtual void _setSkyPlane(
            bool enable,
            const Plane& plane, const String& materialName, Real scale = 1000,
            Real tiling = 10, uint8 renderQueue = RENDER_QUEUE_SKIES_EARLY, Real bow = 0, 
            int xsegments = 1, int ysegments = 1, 
            const String& groupName = ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);

		
		virtual void setSkyPlaneEnabled(bool enable) { mSkyPlaneEnabled = enable; }

		virtual bool isSkyPlaneEnabled(void) const { return mSkyPlaneEnabled; }

		virtual SceneNode* getSkyPlaneNode(void) const { return mSkyPlaneNode; }

		virtual const SkyPlaneGenParameters& getSkyPlaneGenParameters(void) const { return mSkyPlaneGenParameters; }

//         virtual void setSkyBox(
//             bool enable, const String& materialName, Real distance = 5000,
//             bool drawFirst = true, const Quaternion& orientation = Quaternion::IDENTITY,
//             const String& groupName = ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
// 
//         
//         virtual void _setSkyBox(
//             bool enable, const String& materialName, Real distance = 5000,
//             uint8 renderQueue = RENDER_QUEUE_SKIES_EARLY, const Quaternion& orientation = Quaternion::IDENTITY,
//             const String& groupName = ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
//
// 		virtual void setSkyBoxEnabled(bool enable) { mSkyBoxEnabled = enable; }
// 
// 		virtual bool isSkyBoxEnabled(void) const { return mSkyBoxEnabled; }
// 
// 		virtual SceneNode* getSkyBoxNode(void) const { return mSkyBoxNode; }
// 
// 		virtual const SkyBoxGenParameters& getSkyBoxGenParameters(void) const { return mSkyBoxGenParameters; }

        virtual void setSkyDome(
            bool enable, const String& materialName, Real curvature = 10,
            Real tiling = 8, Real distance = 4000, bool drawFirst = true,
            const Quaternion& orientation = Quaternion::IDENTITY,
            int xsegments = 16, int ysegments = 16, int ysegments_keep = -1,
            const String& groupName = ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);

        virtual void _setSkyDome(
            bool enable, const String& materialName, Real curvature = 10,
            Real tiling = 8, Real distance = 4000, uint8 renderQueue = RENDER_QUEUE_SKIES_EARLY,
            const Quaternion& orientation = Quaternion::IDENTITY,
            int xsegments = 16, int ysegments = 16, int ysegments_keep = -1,
            const String& groupName = ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);

		virtual void setSkyDomeEnabled(bool enable) { mSkyDomeEnabled = enable; }

		virtual bool isSkyDomeEnabled(void) const { return mSkyDomeEnabled; }

		virtual SceneNode* getSkyDomeNode(void) const { return mSkyDomeNode; }

		virtual const SkyDomeGenParameters& getSkyDomeGenParameters(void) const { return mSkyDomeGenParameters; }

        void setFog(
            FogMode mode = FOG_NONE, const ColourValue& colour = ColourValue::White,
            Real expDensity = 0.001, Real linearStart = 0.0, Real linearEnd = 1.0);

        virtual FogMode getFogMode(void) const;

        virtual const ColourValue& getFogColour(void) const;

        virtual Real getFogStart(void) const;

        virtual Real getFogEnd(void) const;

        virtual Real getFogDensity(void) const;


        
// 		virtual BillboardSet* createBillboardSet(const String& name, unsigned int poolSize = 20);
// 		virtual BillboardSet* createBillboardSet(unsigned int poolSize = 20);
// 		virtual BillboardSet* getBillboardSet(const String& name) const;
// 		virtual bool hasBillboardSet(const String& name) const;
// 		virtual void destroyBillboardSet(BillboardSet* set);
// 		virtual void destroyBillboardSet(const String& name);
// 		virtual void destroyAllBillboardSets(void);


        virtual void setDisplaySceneNodes(bool display);
        
        virtual bool getDisplaySceneNodes(void) const {return mDisplayNodes;}

        virtual Animation* createAnimation(const String& name, Real length);

        virtual Animation* getAnimation(const String& name) const;
		
		virtual bool hasAnimation(const String& name) const;

        virtual void destroyAnimation(const String& name);

        virtual void destroyAllAnimations(void);

        virtual AnimationState* createAnimationState(const String& animName);

        virtual AnimationState* getAnimationState(const String& animName) const;
		
		virtual bool hasAnimationState(const String& name) const;

        virtual void destroyAnimationState(const String& name);

        virtual void destroyAllAnimationStates(void);

        virtual void manualRender(RenderOperation* rend, Pass* pass, Viewport* vp, 
            const Matrix4& worldMatrix, const Matrix4& viewMatrix, const Matrix4& projMatrix, 
            bool doBeginEndFrame = false) ;

		virtual void manualRender(Renderable* rend, const Pass* pass, Viewport* vp, 
			const Matrix4& viewMatrix, const Matrix4& projMatrix, bool doBeginEndFrame = false, bool lightScissoringClipping = true, 
			bool doLightIteration = true, const LightList* manualLightList = 0);

        virtual RenderQueue* getRenderQueue(void);

        virtual void addRenderQueueListener(RenderQueueListener* newListener);

        virtual void removeRenderQueueListener(RenderQueueListener* delListener);
		
		virtual void addRenderObjectListener(RenderObjectListener* newListener);
		
		virtual void removeRenderObjectListener(RenderObjectListener* delListener);

		virtual void addSpecialCaseRenderQueue(uint8 qid);
		
		virtual void removeSpecialCaseRenderQueue(uint8 qid);
		
		virtual void clearSpecialCaseRenderQueues(void);
		
		virtual void setSpecialCaseRenderQueueMode(SpecialCaseRenderQueueMode mode);
		
		virtual SpecialCaseRenderQueueMode getSpecialCaseRenderQueueMode(void);
		
		virtual bool isRenderQueueToBeProcessed(uint8 qid);

		virtual void setWorldGeometryRenderQueue(uint8 qid);
		
		virtual uint8 getWorldGeometryRenderQueue(void);

		virtual void showBoundingBoxes(bool bShow);

		virtual bool getShowBoundingBoxes() const;

        virtual void _notifyAutotrackingSceneNode(SceneNode* node, bool autoTrack);

        virtual AxisAlignedBoxSceneQuery* 
            createAABBQuery(const AxisAlignedBox& box, unsigned long mask = 0xFFFFFFFF);
        
        virtual SphereSceneQuery* 
            createSphereQuery(const Sphere& sphere, unsigned long mask = 0xFFFFFFFF);
        
        virtual PlaneBoundedVolumeListSceneQuery* 
            createPlaneBoundedVolumeQuery(const PlaneBoundedVolumeList& volumes, unsigned long mask = 0xFFFFFFFF);

        virtual RaySceneQuery* 
            createRayQuery(const Ray& ray, unsigned long mask = 0xFFFFFFFF);
        //PyramidSceneQuery* createPyramidQuery(const Pyramid& p, unsigned long mask = 0xFFFFFFFF);
        
        virtual IntersectionSceneQuery* 
            createIntersectionQuery(unsigned long mask = 0xFFFFFFFF);

        virtual void destroyQuery(SceneQuery* query);

        typedef MapIterator<CameraList> CameraIterator;
        typedef MapIterator<AnimationList> AnimationIterator;

        CameraIterator getCameraIterator(void) {
            return CameraIterator(mCameras.begin(), mCameras.end());
        }
		
		const CameraList& getCameras() const { return mCameras; }
        
        AnimationIterator getAnimationIterator(void) {
            return AnimationIterator(mAnimationsList.begin(), mAnimationsList.end());
        }
		
		const AnimationList& getAnimations() const { return mAnimationsList; }
        
        AnimationStateIterator getAnimationStateIterator(void) {
            return mAnimationStates.getAnimationStateIterator();
        }

        virtual void setShadowTechnique(ShadowTechnique technique);
        
        virtual ShadowTechnique getShadowTechnique(void) const { return mShadowTechnique; }

        virtual void setShowDebugShadows(bool debug) { mDebugShadows = debug; }
        
        virtual bool getShowDebugShadows(void ) const { return mDebugShadows; }

        virtual void setShadowColour(const ColourValue& colour);
        
        virtual const ColourValue& getShadowColour(void) const;
        
        virtual void setShadowDirectionalLightExtrusionDistance(Real dist); 
        
        virtual Real getShadowDirectionalLightExtrusionDistance(void) const;
        
        virtual void setShadowFarDistance(Real distance);
        
        virtual Real getShadowFarDistance(void) const
        { return mDefaultShadowFarDist; }
        virtual Real getShadowFarDistanceSquared(void) const
        { return mDefaultShadowFarDistSquared; }

		virtual void setShadowIndexBufferSize(size_t size);
        /// Get the size of the shadow index buffer
		virtual size_t getShadowIndexBufferSize(void) const
		{ return mShadowIndexBufferSize; }
        
        virtual void setShadowTextureSize(unsigned short size);

		virtual void setShadowTextureConfig(size_t shadowIndex, unsigned short width, 
			unsigned short height, PixelFormat format, unsigned short fsaa = 0, uint16 depthBufferPoolId=1);
		
		virtual void setShadowTextureConfig(size_t shadowIndex, 
			const ShadowTextureConfig& config);

		ConstShadowTextureConfigIterator getShadowTextureConfigIterator() const;

        virtual void setShadowTexturePixelFormat(PixelFormat fmt);
        
        virtual void setShadowTextureFSAA(unsigned short fsaa);

        virtual void setShadowTextureCount(size_t count);
        /// Get the number of the textures allocated for texture based shadows
        size_t getShadowTextureCount(void) const {return mShadowTextureConfigList.size(); }

		void setShadowTextureCountPerLightType(Light::LightTypes type, size_t count)
		{ mShadowTextureCountPerType[type] = count; }
		/// Get the number of shadow textures is assigned for the given light type.
		size_t getShadowTextureCountPerLightType(Light::LightTypes type) const
		{return mShadowTextureCountPerType[type]; }

        virtual void setShadowTextureSettings(unsigned short size, unsigned short count, 
			PixelFormat fmt = PF_X8R8G8B8, unsigned short fsaa = 0, uint16 depthBufferPoolId=1);

		virtual const TexturePtr& getShadowTexture(size_t shadowIndex);

        virtual void setShadowDirLightTextureOffset(Real offset) { mShadowTextureOffset = offset;}
		
		virtual Real getShadowDirLightTextureOffset(void)  const { return mShadowTextureOffset; }
        
        virtual void setShadowTextureFadeStart(Real fadeStart) 
        { mShadowTextureFadeStart = fadeStart; }
        
        virtual void setShadowTextureFadeEnd(Real fadeEnd) 
        { mShadowTextureFadeEnd = fadeEnd; }

		virtual void setShadowTextureSelfShadow(bool selfShadow); 

		/// Gets whether or not texture shadows attempt to self-shadow.
		virtual bool getShadowTextureSelfShadow(void) const 
		{ return mShadowTextureSelfShadow; }
		
		virtual void setShadowTextureCasterMaterial(const String& name);
		
		virtual void setShadowTextureReceiverMaterial(const String& name);

		virtual void setShadowCasterRenderBackFaces(bool bf) { mShadowCasterRenderBackFaces = bf; }

		virtual bool getShadowCasterRenderBackFaces() const { return mShadowCasterRenderBackFaces; }

		virtual void setShadowCameraSetup(const ShadowCameraSetupPtr& shadowSetup);

		virtual const ShadowCameraSetupPtr& getShadowCameraSetup() const;

        virtual void setShadowUseInfiniteFarPlane(bool enable) {
            mShadowUseInfiniteFarPlane = enable; }

		virtual bool isShadowTechniqueStencilBased(void) const 
		{ return (mShadowTechnique & SHADOWDETAILTYPE_STENCIL) != 0; }
		
		virtual bool isShadowTechniqueTextureBased(void) const 
		{ return (mShadowTechnique & SHADOWDETAILTYPE_TEXTURE) != 0; }
		
		virtual bool isShadowTechniqueModulative(void) const 
		{ return (mShadowTechnique & SHADOWDETAILTYPE_MODULATIVE) != 0; }
		
		virtual bool isShadowTechniqueAdditive(void) const 
		{ return (mShadowTechnique & SHADOWDETAILTYPE_ADDITIVE) != 0; }
		
		virtual bool isShadowTechniqueIntegrated(void) const 
		{ return (mShadowTechnique & SHADOWDETAILTYPE_INTEGRATED) != 0; }
		
		virtual bool isShadowTechniqueInUse(void) const 
		{ return mShadowTechnique != SHADOWTYPE_NONE; }
		
		virtual void setShadowUseLightClipPlanes(bool enabled) { mShadowAdditiveLightClip = enabled; }
		
		virtual bool getShadowUseLightClipPlanes() const { return mShadowAdditiveLightClip; }

		virtual void _setActiveCompositorChain(CompositorChain* chain) { mActiveCompositorChain = chain; }

		virtual void setLateMaterialResolving(bool isLate) { mLateMaterialResolving = isLate; }
		
		virtual bool isLateMaterialResolving() const { return mLateMaterialResolving; }

		virtual CompositorChain* _getActiveCompositorChain() const { return mActiveCompositorChain; }

		virtual void addListener(Listener* s);
		
		virtual void removeListener(Listener* s);

		virtual StaticGeometry* createStaticGeometry(const String& name);
		
		virtual StaticGeometry* getStaticGeometry(const String& name) const;
		
		virtual bool hasStaticGeometry(const String& name) const;
		
		virtual void destroyStaticGeometry(StaticGeometry* geom);
		
		virtual void destroyStaticGeometry(const String& name);
		
		virtual void destroyAllStaticGeometry(void);

		virtual InstancedGeometry* createInstancedGeometry(const String& name);
		
		virtual InstancedGeometry* getInstancedGeometry(const String& name) const;
		
		virtual void destroyInstancedGeometry(InstancedGeometry* geom);
		
		virtual void destroyInstancedGeometry(const String& name);
		
		virtual void destroyAllInstancedGeometry(void);

		virtual InstanceManager* createInstanceManager( const String &customName, const String &meshName,
														const String &groupName,
														InstanceManager::InstancingTechnique technique,
														size_t numInstancesPerBatch, uint16 flags=0,
														unsigned short subMeshIdx=0 );

		virtual InstanceManager* getInstanceManager( const String &managerName ) const;

		virtual bool hasInstanceManager( const String &managerName ) const;

		virtual void destroyInstanceManager( const String &name );
		virtual void destroyInstanceManager( InstanceManager *instanceManager );

		virtual void destroyAllInstanceManagers(void);

		virtual size_t getNumInstancesPerBatch( const String &meshName, const String &groupName,
												const String &materialName,
												InstanceManager::InstancingTechnique technique,
												size_t numInstancesPerBatch, uint16 flags=0,
												unsigned short subMeshIdx=0 );

		virtual InstancedEntity* createInstancedEntity( const String &materialName,
														const String &managerName );

		virtual void destroyInstancedEntity( InstancedEntity *instancedEntity );

		void _addDirtyInstanceManager( InstanceManager *dirtyManager );

		virtual MovableObject* createMovableObject(const String& name, 
			const String& typeName, const NameValuePairList* params = 0);
		
		virtual MovableObject* createMovableObject(const String& typeName, const NameValuePairList* params = 0);
		
		virtual void destroyMovableObject(const String& name, const String& typeName);
		
		virtual void destroyMovableObject(MovableObject* m);
		
		virtual void destroyAllMovableObjectsByType(const String& typeName);
		
		virtual void destroyAllMovableObjects(void);
		
		virtual MovableObject* getMovableObject(const String& name, const String& typeName) const;
		
		virtual bool hasMovableObject(const String& name, const String& typeName) const;
		typedef MapIterator<MovableObjectMap> MovableObjectIterator;
		
		virtual MovableObjectIterator getMovableObjectIterator(const String& typeName);
		
		virtual void injectMovableObject(MovableObject* m);
		
		virtual void extractMovableObject(const String& name, const String& typeName);
		
		virtual void extractMovableObject(MovableObject* m);
		
		virtual void extractAllMovableObjectsByType(const String& typeName);

		virtual void setVisibilityMask(uint32 vmask) { mVisibilityMask = vmask; }

		virtual uint32 getVisibilityMask(void) { return mVisibilityMask; }

		uint32 _getCombinedVisibilityMask(void) const;

		virtual void setFindVisibleObjects(bool find) { mFindVisibleObjects = find; }

		virtual bool getFindVisibleObjects(void) { return mFindVisibleObjects; }

		virtual void setNormaliseNormalsOnScale(bool n) { mNormaliseNormalsOnScale = n; }

		virtual bool getNormaliseNormalsOnScale() const { return mNormaliseNormalsOnScale; }

		virtual void setFlipCullingOnNegativeScale(bool n) { mFlipCullingOnNegativeScale = n; }

		virtual bool getFlipCullingOnNegativeScale() const { return mFlipCullingOnNegativeScale; }

		virtual void _injectRenderWithPass(Pass *pass, Renderable *rend, bool shadowDerivation = true,
			bool doLightIteration = false, const LightList* manualLightList = 0);

		virtual void _suppressRenderStateChanges(bool suppress);
		
		virtual bool _areRenderStateChangesSuppressed(void) const
		{ return mSuppressRenderStateChanges; }

        virtual const Pass* _setPass(const Pass* pass, 
			bool evenIfSuppressed = false, bool shadowDerivation = true);
		
		virtual void _markGpuParamsDirty(uint16 mask);

		virtual void _suppressShadows(bool suppress); 

		virtual bool _areShadowsSuppressed(void) const
		{ return mSuppressShadows; }

		virtual void _renderQueueGroupObjects(RenderQueueGroup* group, 
			QueuedRenderableCollection::OrganisationMode om);

		
		void setQueuedRenderableVisitor(SceneMgrQueuedRenderableVisitor* visitor);

		
		SceneMgrQueuedRenderableVisitor* getQueuedRenderableVisitor(void) const;


		
		RenderSystem *getDestinationRenderSystem();

		
		Viewport* getCurrentViewport(void) const { return mCurrentViewport; }

		
		const VisibleObjectsBoundsInfo& getVisibleObjectsBoundsInfo(const Camera* cam) const;

		
		const VisibleObjectsBoundsInfo& getShadowCasterBoundsInfo(const Light* light, size_t iteration = 0) const;

		
		virtual void setCameraRelativeRendering(bool rel) { mCameraRelativeRendering = rel; }

		
		virtual bool getCameraRelativeRendering() const { return mCameraRelativeRendering; }


        
        void addLodListener(LodListener *listener);

        /**
        Remove a level of detail listener.
        @remarks
            Do not call from inside an LodListener callback method.
        */
        void removeLodListener(LodListener *listener);

        
        void _notifyMovableObjectLodChanged(MovableObjectLodChangedEvent& evt);

        
        void _notifyEntityMeshLodChanged(EntityMeshLodChangedEvent& evt);

        
        void _notifyEntityMaterialLodChanged(EntityMaterialLodChangedEvent& evt);

        
        void _handleLodEvents();
    };

    
    class _OgreExport DefaultIntersectionSceneQuery : 
        public IntersectionSceneQuery
    {
    public:
        DefaultIntersectionSceneQuery(SceneManager* creator);
        ~DefaultIntersectionSceneQuery();

        
        void execute(IntersectionSceneQueryListener* listener);
    };

    
	class _OgreExport DefaultRaySceneQuery : public RaySceneQuery
    {
    public:
        DefaultRaySceneQuery(SceneManager* creator);
        ~DefaultRaySceneQuery();

        
        void execute(RaySceneQueryListener* listener);
    };
    
	class _OgreExport DefaultSphereSceneQuery : public SphereSceneQuery
    {
    public:
        DefaultSphereSceneQuery(SceneManager* creator);
        ~DefaultSphereSceneQuery();

        
        void execute(SceneQueryListener* listener);
    };
    
    class _OgreExport DefaultPlaneBoundedVolumeListSceneQuery : public PlaneBoundedVolumeListSceneQuery
    {
    public:
        DefaultPlaneBoundedVolumeListSceneQuery(SceneManager* creator);
        ~DefaultPlaneBoundedVolumeListSceneQuery();

        
        void execute(SceneQueryListener* listener);
    };
    
	class _OgreExport DefaultAxisAlignedBoxSceneQuery : public AxisAlignedBoxSceneQuery
    {
    public:
        DefaultAxisAlignedBoxSceneQuery(SceneManager* creator);
        ~DefaultAxisAlignedBoxSceneQuery();

        
        void execute(SceneQueryListener* listener);
    };
    

	/// Bitmask containing scene types
	typedef uint16 SceneTypeMask;

	
	enum SceneType
	{
		ST_GENERIC = 1,
		ST_EXTERIOR_CLOSE = 2,
		ST_EXTERIOR_FAR = 4,
		ST_EXTERIOR_REAL_FAR = 8,
		ST_INTERIOR = 16
	};

	
	struct SceneManagerMetaData
	{
		/// A globally unique string identifying the scene manager type
		String typeName;
		/// A text description of the scene manager
		String description;
		/// A mask describing which sorts of scenes this manager can handle
		SceneTypeMask sceneTypeMask;
		/// Flag indicating whether world geometry is supported
		bool worldGeometrySupported;
	};



	
	class _OgreExport SceneManagerFactory : public MemAlloc_SceneCtrl
	{
	protected:
		mutable SceneManagerMetaData mMetaData;
		mutable bool mMetaDataInit;
		/// Internal method to initialise the metadata, must be implemented
		virtual void initMetaData(void) const = 0;
	public:
		SceneManagerFactory() : mMetaDataInit(true) {}
		virtual ~SceneManagerFactory() {}
		
		virtual const SceneManagerMetaData& getMetaData(void) const 
		{
			if (mMetaDataInit)
			{
				initMetaData();
				mMetaDataInit = false;
			}
			return mMetaData; 
		}
		
		virtual SceneManager* createInstance(const String& instanceName) = 0;
		
		virtual void destroyInstance(SceneManager* instance) = 0;

	};

	
	


} // Namespace



#endif
